package geradatawarehouse.dao.postgres.abs;

import geradatawarehouse.dao.abs.AbstractDAO;
import geradatawarehouse.dao.config.ConnectionConfiguration;

import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Date;

public class PostgresDAO extends AbstractDAO {

	/**
	 * Conexão com a base de dados. Utilizada em controle de transações.
	 */
	protected Connection conn;

	/**
	 * Flag para a abertura de transactions.
	 */
	private boolean transactionStarted;

	protected PostgresDAO() throws IOException {
		super(ConnectionConfiguration.DatabaseType.POSTGRES);
	}

	/**
	 * @throws SQLException
	 */
	public void commitTransaction() throws SQLException {
		try {
			this.conn.commit();
		} catch (final SQLException e) {
			this.treatTransactionException();
			throw e;
		}
	}

	protected String generateInsertBooleanValue(final Boolean b) {

		if (b == null) {
			return "NULL";
		} else if (b) {
			return "TRUE";
		}

		return "FALSE";
	}

	protected String generateInsertDateValue(final Date d) {

		if (d != null) {
			return "'" + this.formatDate(d) + "'";
		}

		return "NULL";
	}

	/**
	 * Inicia uma transaction. Se já houver um transaction aberto, retorna sem
	 * abrir outro. Caso haja um erro, a operação rollback acontecerá
	 * automaticamente.
	 * 
	 * @throws SQLException
	 */
	public void startTransaction() throws SQLException {

		// Somente se já não foi iniciada (esta classe não deve ser
		// compartilhada por threads).
		if (!this.transactionStarted) {
			this.conn = this.buildConnection();
			this.conn.setAutoCommit(false);
			this.transactionStarted = true;
		}

	}

	/**
	 * Trata exceções em transactions, efetuando rollback em uma transação se
	 * for o caso
	 * 
	 * @throws SQLException
	 */
	protected void treatTransactionException() throws SQLException {
		try {
			if (this.transactionStarted) {
				this.conn.rollback();
			}
		} finally {
			if (!this.conn.isClosed()) {
				this.conn.close();
			}
		}
	}

}
